#ifndef UDP_BLOCKS_H
#define UDP_BLOCKS_H
#include "base.h"

class UdpRequest
{
 public:
  UdpRequest ()
    {
      m_usRequestId = 0;
      m_uiSubRequestId = 0;
    }
  void DeSerialize(const string& bk);
  void Serialize(string& bk);
  unsigned short m_usRequestId;	/* the id of the query in the testing file */
  unsigned int m_uiSubRequestId;  /* subrequest id < 100,000 items */
  string m_strHashKi;             /* lookup key */
};


class UdpBlock
{
 public:
  UdpBlock ()
    {
      m_usRequestId = 0;
      m_uiSubRequestId = 0;
      m_usBlockId = 0;
      m_usBlocksTotal = 0;
	  m_bLast = false;
      m_strContent.reserve(Config::m_udp_block_size);
    }
  bool IsLast()
	{
	  return (m_usBlocksTotal == 0);
	}
  void DeSerialize(string bk);
  unsigned short m_usRequestId;	/* the id of the query in the testing file */
  unsigned int m_uiSubRequestId;  /* subrequest id < 100,000 items */
  unsigned short m_usBlockId;	  /* position inside a whole response 65535 enough*/
  unsigned short m_usBlocksTotal;  /* total number of blocks in one response, 0 indicating the last response */
  
  bool m_bLast;					   /* belong to the response to last subrequestid */
  string m_strContent;		  /* payload */
};

class UdpResponse
{
 public:
  UdpResponse();
  ~UdpResponse();
  void SetNumBlocks (unsigned short sz);
  void Insert (UdpBlock* pblk);
  bool IsComplete();
  bool Exists(UdpBlock* pblk);
  bool& IsOutputted() 
	{
	  pthread_mutex_lock(&m_mutex);
	  return m_bOutputted;
	  pthread_mutex_unlock(&m_mutex);
	}
  bool& IsLastResp() 
	{
	  pthread_mutex_lock(&m_mutex);
	  for (size_t i = 0; i < m_vecBlocks.size(); i++)
		{
		  if (m_vecBlocks[i] != NULL)
			return m_vecBlocks[i]->m_bLast;
		}
	  pthread_mutex_unlock(&m_mutex);
	}
  unsigned int& ResponseId() { return m_uiSubRequestId; }
 private:
  vector<UdpBlock * > m_vecBlocks; /* map blockid to block */
  unsigned short m_usRequestId;
  unsigned int m_uiSubRequestId;
  unsigned short m_usBlocksTotal; /* set from udpblock */
  unsigned short m_usBlocksReceived;  /* increment for each new arrival */
  unsigned short m_usBlocksToReceive; /* m_usBlocksTotal - #received */
  bool m_bOutputted;
  pthread_mutex_t m_mutex;
};

#endif
